<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------

/**
 * Think 基础函数库
 *
 * @category wxapi
 * @package Common
 * @author tradewind888
 */
/*****************以下用于爱农支付*********************/
function createLinkstring($para) {
	$arg  = "";
	while (list ($key, $val) = each ($para)) {
		$arg.=$key."=".$val."&";
	}
	//去掉最后一个&字符
	$arg = substr($arg,0,count($arg)-2);

	return $arg;
}
/**
 * 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串，并对字符串做urlencode编码
 * @param $para 需要拼接的数组
 * return 拼接完成以后的字符串
 */
function createLinkstringUrlencode($para) {
	$arg  = "";
	while (list ($key, $val) = each ($para)) {

		$arg.=urlencode($key)."=".urlencode($val)."&";
	}
	//去掉最后一个&字符
	$arg = substr($arg,0,count($arg)-2);

	return $arg;
}
/**
 * 除去数组中的签名参数
 * @param $para 签名参数组
 * return 去掉签名参数后的新签名参数组
 */
function paraFilter($para) {
	$para_filter = array();
	while (list ($key, $val) = each ($para)) {
		if($key == "signature" || $key == "signMethod") continue;
		else	$para_filter[$key] = $para[$key];
	}
	return $para_filter;
}
/**
 * 对数组排序
 * @param $para 排序前的数组
 * return 排序后的数组
 */
function argSort($para) {
	ksort($para);
	reset($para);
	return $para;
}
/**
 * 写日志，方便测试（看网站需求，也可以改成把记录存入数据库）
 * 注意：服务器需要开通fopen配置
 * @param $log_dir日志路径，$word 要写入日志里的文本内容 默认值：空值
 */
function logResult($log_dir,$word='') {
	$fp = fopen($log_dir,"a");
	flock($fp, LOCK_EX) ;
	fwrite($fp,"执行日期：".strftime("%Y%m%d%H%M%S",time())."\r\n".$word."\r\n");
	flock($fp, LOCK_UN);
	fclose($fp);
}

/**
 * 远程获取数据，POST模式
 * 注意：
 * 1.使用Crul需要修改服务器中php.ini文件的设置，找到php_curl.dll去掉前面的";"就行了
 * 2.文件夹中cacert.pem是SSL证书请保证其路径有效，目前默认路径是：getcwd().'\certificates\cacert.pem'
 * @param $url 指定请求URL完整路径地址
 * @param $cacert_url 指定当前证书的存放路径
 * @param $para 请求的数据包
 * return 远程输出的结果
 */
function curlRequestPOST($url, $cacert_url, $para) {

	$curl = curl_init($url);
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
	curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
	curl_setopt($curl, CURLOPT_CAINFO,$cacert_url);
	curl_setopt($curl, CURLOPT_HEADER, 0 );
	curl_setopt($curl,CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($curl,CURLOPT_POST,true);
	curl_setopt($curl,CURLOPT_POSTFIELDS,$para);
	$responseText = curl_exec($curl);
	//var_dump( curl_error($curl) );//如果执行curl过程中出现异常，可打开此注释查看异常内容
	curl_close($curl);

	return $responseText;
}

/**
 * MD5签名字符串
 * @param $prestr 需要签名的字符串
 * @param $key 私钥
 * return 签名结果
 */
function md5Sign($prestr, $key) {
	$prestr = $prestr . $key;
	return base64_encode(md5($prestr,TRUE));
}

/**
 * MD5验证签名
 * @param $prestr 需要签名的字符串
 * @param $sign 签名结果
 * @param $key 私钥
 * return 签名结果
 */
function md5Verify($prestr, $sign, $key) {
	$prestr = $prestr . $key;
	$mysgin = base64_encode(md5($prestr,TRUE));

	if($mysgin == $sign) {
		return true;
	}
	else {
		return false;
	}
}


/**
 * 转化返回报文字符串为解码后的数组
 * @param $return_str 同步返回来的报文字符串
 * @param $base64_field 需要base64解码的参数数组,默认值为空数组
 * @return 数组
 */
function strToArray($return_str,$base64_field=array()){
	$res_arr=array();
	$arr_temp=explode('&',$return_str);
	foreach($arr_temp as $v){
		$arr=explode('=',$v);
		$res_arr[$arr[0]]= substr($v,strlen($arr[0])+1);
	}

	//对部分参数值进行base64_decode解码
	if(empty($base64_field) )  return $res_arr;
	foreach($base64_field as $v){
		isset($res_arr[$v])  &&  ($res_arr[$v]= base64_decode($res_arr[$v]));
	}
	return $res_arr;
}


/**
 * 获取返回时的签名验证结果
 * @param $para_temp 参数数组
 * @param $key 私钥
 * @return 签名验证结果
 */
function getSignVeryfy($para_temp,$key)
{
//除去待验签参数数组中签名参数
	$para_filter = paraFilter($para_temp);

//对待签名参数数组排序
	$para_sort = argSort($para_filter);

//把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
	$prestr = createLinkstring($para_sort);

	$isSgin = false;
	switch (strtoupper($para_temp['signMethod'])) {
		case "MD5" :
			$isSgin = md5Verify($prestr, $para_temp['signature'], $key);
			break;
		default :
			$isSgin = false;
	}

	return $isSgin;
}

/*****************以上用于爱农支付*********************/




/**
 * 将字符串中emoji转换成Unicode编码模式保存
 * @param $str /需要处理的字符串
 * @return string
 */
function emojiToUnicode($str){
	$str = json_encode($str);
	//$tmpStr = preg_replace("#(\\\u[e|d][0-9a-f]{3})#ie","addslashes('\\1')",$str); //将emoji的unicode留下，其他不动
	//$tmpStr = preg_replace("#(\\\u[e|d][0-9a-f]{3})#ie"," ",$str); //将emoji的unicode留下，其他不动
	$tmpStr = preg_replace("#(\\\u[b][0-9a-f]{3})#ie"," ",$str); //将emoji的unicode留下，其他不动
	Log::write('tiaoshi:'.$tmpStr);
	return json_decode($tmpStr);
}


/**
 * 对查询结果集进行排序
 * @param array $list 查询结果
 * @param string $field 排序的字段名
 * @param array $sortby 排序类型
 * asc正向排序 desc逆向排序 nat自然排序
 * @return array
 */

function list_sort_by($list,$field, $sortby='asc') {
	if(is_array($list)){
		$refer = $resultSet = array();
		foreach ($list as $i => $data)
			$refer[$i] = &$data[$field];
		switch ($sortby) {
			case 'asc': // 正向排序
				asort($refer);
				break;
			case 'desc':// 逆向排序
				arsort($refer);
				break;
			case 'nat': // 自然排序
				natcasesort($refer);
				break;
		}
		foreach ( $refer as $key=> $val)
			$resultSet[] = &$list[$key];
		return $resultSet;
	}
	return false;
}

// 验证手机号，暂时就验证是否数字就行了
function validation_filter_mobile_number($mobile_number) {
	if (is_numeric ( $mobile_number ) && (strlen ( $mobile_number ) == 11))
		return true;
	return false;
}

// 验证身份证号
function validation_filter_id_card($id_card) {
	if (strlen ( $id_card ) == 18) {
		return idcard_checksum18 ( $id_card );
	} elseif ((strlen ( $id_card ) == 15)) {
		$id_card = idcard_15to18 ( $id_card );
		return idcard_checksum18 ( $id_card );
	} else {
		return false;
	}
}
function format_date($time){
	$t=time()-$time;
	$f=array(
		'31536000'=>'年',
		'2592000'=>'个月',
		'604800'=>'星期',
		'86400'=>'天',
		'3600'=>'小时',
		'60'=>'分钟',
		'1'=>'秒'
	);
	if($t>0){
		foreach ($f as $k=>$v)    {
			if (0 !=$c=floor($t/(int)$k)) {
				return $c.$v.'前';
			}
		}
	} else {
		return '1秒前';
	}
}
// 计算身份证校验码，根据国家标准GB 11643-1999
function idcard_verify_number($idcard_base) {
	if (strlen ( $idcard_base ) != 17) {
		return false;
	}
	// 加权因子
	$factor = array (
		7,
		9,
		10,
		5,
		8,
		4,
		2,
		1,
		6,
		3,
		7,
		9,
		10,
		5,
		8,
		4,
		2
	);
	// 校验码对应值
	$verify_number_list = array (
		'1',
		'0',
		'X',
		'9',
		'8',
		'7',
		'6',
		'5',
		'4',
		'3',
		'2'
	);
	$checksum = 0;
	for($i = 0; $i < strlen ( $idcard_base ); $i ++) {
		$checksum += substr ( $idcard_base, $i, 1 ) * $factor [$i];
	}
	$mod = $checksum % 11;
	$verify_number = $verify_number_list [$mod];
	return $verify_number;
}

// 将15位身份证升级到18位
function idcard_15to18($idcard) {
	if (strlen ( $idcard ) != 15) {
		return false;
	} else {
		// 如果身份证顺序码是996 997 998 999，这些是为百岁以上老人的特殊编码
		if (array_search ( substr ( $idcard, 12, 3 ), array (
				'996',
				'997',
				'998',
				'999'
			) ) !== false) {
			$idcard = substr ( $idcard, 0, 6 ) . '18' . substr ( $idcard, 6, 9 );
		} else {
			$idcard = substr ( $idcard, 0, 6 ) . '19' . substr ( $idcard, 6, 9 );
		}
	}
	$idcard = $idcard . idcard_verify_number ( $idcard );
	return $idcard;
}

// 18位身份证校验码有效性检查
function idcard_checksum18($idcard) {
	if (strlen ( $idcard ) != 18) {
		return false;
	}
	$idcard_base = substr ( $idcard, 0, 17 );
	if (idcard_verify_number ( $idcard_base ) != strtoupper ( substr ( $idcard, 17, 1 ) )) {
		return false;
	} else {
		return true;
	}
}

/*
 * 缩小并剪裁图片
 */
function resizeimage($src, $dest, $newwidth, $newheight) {
	// Load
	list ( $width, $height ) = getimagesize ( $src );
	$thumb = imagecreatetruecolor ( $newwidth, $newheight );
	$source = imagecreatefromjpeg ( $src );

	// Resize
	imagecopyresized ( $thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height );

	// Output
	imagejpeg ( $thumb, $dest );
}
function download_file($imgUrl){

	$ch = curl_init($imgUrl);
	curl_setopt($ch, CURLOPT_HEADER, 0);
	curl_setopt($ch, CURLOPT_NOBODY, 0);
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	$package = curl_exec($ch);
	$httpinfo = curl_getinfo($ch);
	curl_close($ch);
	$extension = '.jpg';
	$filename = md5 ( $imgUrl );

	$img_url = $filename . $extension;
	$lp = LOCAL_PIC_PATH . $img_url;
	$fp = fopen($lp, 'w');
	fwrite($fp, $package);
	fclose($fp);
	return $img_url;
}

/*
 * 按照小边裁剪正方形或者按照宽等比缩放
 */
function thumb($image, $thumbname, $type = '', $maxWidth = 200, $maxHeight = 50, $isSquare=true,$interlace = true) {
	// 获取原图信息
	$info = getImageInfo ( $image );
	if ($info !== false) {
		$srcWidth = $info ['width'];
		$srcHeight = $info ['height'];

		$type = empty ( $type ) ? $info ['type'] : $type;
		$type = strtolower ( $type );
		$interlace = $interlace ? 1 : 0;
		unset ( $info );
		if($isSquare){
			$scale = min ( $maxWidth / $srcWidth, $maxHeight / $srcHeight ); // 计算缩放比例
		}else{
			$scale = $maxWidth / $srcWidth; // 计算缩放比例
		}
		if ($scale >= 1) {
			// 超过原图大小不再缩略
			$width = min ( $srcWidth, $srcHeight );
			$height = min ( $srcWidth, $srcHeight );
		} else {
			if($isSquare){
				// 缩略图尺寸
				$width = min ( ( int ) ($srcWidth * $scale), ( int ) ($srcHeight * $scale) );
				$height = min ( ( int ) ($srcWidth * $scale), ( int ) ($srcHeight * $scale) );
			}else{
				$width = ( int ) ($srcWidth * $scale) ;
				$height = ( int ) ($srcHeight * $scale) ;
			}
		}
// 		Log::write("width==".$width."==height==".$height);
		// 载入原图
		$createFun = 'ImageCreateFrom' . ($type == 'jpg' ? 'jpeg' : $type);
		if (! function_exists ( $createFun )) {
			return false;
		}
		$srcImg = $createFun ( $image );

		// 创建缩略图
		if ($type != 'gif' && function_exists ( 'imagecreatetruecolor' ))
			$thumbImg = imagecreatetruecolor ( $width, $height );
		else
			$thumbImg = imagecreate ( $width, $height );
		// png和gif的透明处理 by luofei614
		if ('png' == $type) {
			imagealphablending ( $thumbImg, false ); // 取消默认的混色模式（为解决阴影为绿色的问题）
			imagesavealpha ( $thumbImg, true ); // 设定保存完整的 alpha 通道信息（为解决阴影为绿色的问题）
		} elseif ('gif' == $type) {
			$trnprt_indx = imagecolortransparent ( $srcImg );
			if ($trnprt_indx >= 0) {
				// its transparent
				$trnprt_color = imagecolorsforindex ( $srcImg, $trnprt_indx );
				$trnprt_indx = imagecolorallocate ( $thumbImg, $trnprt_color ['red'], $trnprt_color ['green'], $trnprt_color ['blue'] );
				imagefill ( $thumbImg, 0, 0, $trnprt_indx );
				imagecolortransparent ( $thumbImg, $trnprt_indx );
			}
		}
		// 复制图片
		if (function_exists ( "ImageCopyResampled" ))
			imagecopyresampled ( $thumbImg, $srcImg, 0, 0, 0, 0, $width, $height, $srcWidth, $srcHeight );
		else
			imagecopyresized ( $thumbImg, $srcImg, 0, 0, 0, 0, $width, $height, $srcWidth, $srcHeight );

		// 对jpeg图形设置隔行扫描
		if ('jpg' == $type || 'jpeg' == $type)
			imageinterlace ( $thumbImg, $interlace );

		// 生成图片
		$imageFun = 'image' . ($type == 'jpg' ? 'jpeg' : $type);
		$imageFun ( $thumbImg, $thumbname );
		imagedestroy ( $thumbImg );
		imagedestroy ( $srcImg );
		return $thumbname;
	}
	return false;
}
function getImageInfo($img) {
	$imageInfo = getimagesize ( $img );
	if ($imageInfo !== false) {
		$imageType = strtolower ( substr ( image_type_to_extension ( $imageInfo [2] ), 1 ) );
		$imageSize = filesize ( $img );
		$info = array (
			"width" => $imageInfo [0],
			"height" => $imageInfo [1],
			"type" => $imageType,
			"size" => $imageSize,
			"mime" => $imageInfo ['mime']
		);
		return $info;
	} else {
		return false;
	}
}
function getPageCount($count,$pageSize) {
	if($count % $pageSize==0) {
		return $count / $pageSize;
	} else {
		return ($count-$count% $pageSize)/$pageSize +1;
	}
}
/**
 * Strip close comment and close php tags from file headers used by WP.
 * See http://core.trac.wordpress.org/ticket/8497
 *
 *
 * @param string $str
 * @return string
 */
function _cleanup_header_comment($str) {
	return trim ( preg_replace ( "/\s*(?:\*\/|\?>).*/", '', $str ) );
}

/**
 * Retrieve metadata from a file.
 *
 * Searches for metadata in the first 8kiB of a file, such as a plugin or theme.
 * Each piece of metadata must be on its own line. Fields can not span multiple
 * lines, the value will get cut at the end of the first line.
 *
 * If the file data is not within that first 8kiB, then the author should correct
 * their plugin file and move the data headers to the top.
 *
 * @see http://codex.wordpress.org/File_Header
 *
 * @param string $file
 *        	Path to the file
 * @param array $default_headers
 *        	List of headers, in the format array('HeaderKey' => 'Header Name')
 * @param string $context
 *        	If specified adds filter hook "extra_{$context}_headers"
 */
function get_file_data($file, $default_headers, $context = '') {
	// We don't need to write to the file, so just open for reading.
	$fp = fopen ( $file, 'r' );

	// Pull only the first 8kiB of the file in.
	$file_data = fread ( $fp, 8192 );

	// PHP will close file handle, but we are good citizens.
	fclose ( $fp );

	// Make sure we catch CR-only line endings.
	$file_data = str_replace ( "\r", "\n", $file_data );

	if ($context && $extra_headers = apply_filters ( "extra_{$context}_headers", array () )) {
		$extra_headers = array_combine ( $extra_headers, $extra_headers ); // keys equal values
		$all_headers = array_merge ( $extra_headers, ( array ) $default_headers );
	} else {
		$all_headers = $default_headers;
	}

	foreach ( $all_headers as $field => $regex ) {
		if (preg_match_all ( '/^[ \t\/*#@]*' . preg_quote ( $regex, '/' ) . ':(.*)$/mi', $file_data, $match ) && count ( $match [1] ) > 0) {
			if (count ( $match [1] ) == 1) {
				$all_headers [$field] = _cleanup_header_comment ( $match [1] [0] );
			} else {
				$result = array ();
				foreach ( $match [1] as $value ) {
					array_push ( $result, _cleanup_header_comment ( $value ) );
				}
				$all_headers [$field] = $result;
			}
		} else
			$all_headers [$field] = '';
	}

	return $all_headers;
}

/*
 * 保存图片到本地路径并更改路径的返回地址，如果本地已经存在直接修改路径值
 */
function get_cache_image(&$url) {

	$filename = md5 ( $url );
	$lp = LOCAL_PIC_PATH . $filename;
	$lp6 = LOCAL_PIC_PATH . $filename . ".640";
	$rp = $filename;
	if (! file_exists ( $lp )) {

		Log::write ('first time to load pic :'. $url );
		// 将远程图片取md5保存在本地文件夹,先保存临时文件，然后再改为正式文件
		Http::curlDownload ( $url, $lp . ".tmp" );
		rename ( $lp . ".tmp", $lp );
		// 制作缩略图
		thumb ( $lp, $lp . ".640", "jpg", 640, 720 ,false);
		thumb ( $lp, $lp . ".200", "jpg", 200, 200 ,true);

		//thumb ( $lp . ".tmp", $lp . ".320", "jpg", 320, 320 ,false);
	}else{
		if(! file_exists ( $lp . ".640" )){
			thumb ( $lp, $lp . ".640", "jpg", 640, 720 ,false);
		}
	}
	$url = $rp;
	return $url;
}

function get_session_url(&$url, $customerId, $userName) {
	if ($url == '' || $url == NULL) {
		return $url;
	}
	if (!isset($userName)) {
		$userName = '';
	}
	if (strstr($url, '?')) {
		$urlUserName = strstr($url, 'userName');
		if ($urlUserName) {
			$arrUserName = explode("&", $urlUserName);
			$url = str_replace($arrUserName[0], "userName=" . $userName, $url);
		}

		// 微信路由器项目
		$urlOpenId = strstr($url, 'openid');
		if ($urlOpenId) {
			$arrOpenId = explode("&", $urlOpenId);
			$url = str_replace($arrOpenId[0], "openid=" . $userName, $url);
		}
	}
	return $url;
}

/**********
 * 发送邮件 *
 **********/
function SendMail($address,$title,$message,$ccAddress=null,$bccAddress=null)
{
	vendor('PHPMailer.class#phpmailer');

	$mail=new PHPMailer();
	// 设置PHPMailer使用SMTP服务器发送Email
	$mail->IsSMTP();

	// 设置邮件的字符编码，若不指定，则为'UTF-8'
	$mail->CharSet='UTF-8';

	//用,分隔多个地址
	$addArr = explode(',',$address);
	foreach($addArr as $add){
		$mail->AddAddress($add);
	}
	// 添加收件人地址，可以多次使用来添加多个收件人
	//$mail->AddAddress($address);

	//添加抄送
	if($ccAddress != null){
		//用,分隔多个地址
		$ccArr = explode(',',$ccAddress);
		foreach($ccArr as $cc){
			$mail->AddCC($cc);
		}
	}

	//添加密送
	if($bccAddress != null){
		//用;分隔多个地址
		$bccArr = explode(';',$bccAddress);
		foreach($bccArr as $bcc){
			$mail->AddBCC($bcc);
		}
	}

	//邮件正文支持多媒体,html
	$mail->AltBody="text/html";

	// 设置邮件正文
	$mail->Body=$message;

	// 设置邮件头的From字段。
	$mail->From=C('MAIL_ADDRESS');

	// 设置发件人名字
	$mail->FromName= C('MAIL_SENDER');

	// 设置邮件标题
	$mail->Subject=$title;

	// 设置SMTP服务器。
	$mail->Host=C('MAIL_SMTP');
	$mail->SMTPSecure = C('MAIL_SSL');
	$port = C('MAIL_PORT');
	if(isset($port)){
		$mail->Port  = $port;
	}
	// 设置为"需要验证"
	$mail->SMTPAuth=true;

	// 设置用户名和密码。
	$mail->Username=C('MAIL_LOGINNAME');
	$mail->Password=C('MAIL_PASSWORD');

	\Log::write('lp_1_' . json_encode($mail));
	// 发送邮件。
	$result = $mail->Send();
	if (!$result) {
		Log::write("send mail error:". $mail->ErrorInfo);
	}
	return($result);
}

function mbstr_pad($input , $pad_length ,$pad_string , $pad_type){
	$strlen = (strlen($input) + mb_strlen($input,'UTF8')) / 2;
	if($strlen < $pad_length){
		$difference = $pad_length - $strlen;
		switch ($pad_type) {
			case STR_PAD_RIGHT:
				return $input . str_repeat($pad_string, $difference);
				break;
			case STR_PAD_LEFT:
				return str_repeat($pad_string, $difference) . $input;
				break;
			default:
				$left = $difference / 2;
				$right = $difference - $left;
				return str_repeat($pad_string, $left) . $input . str_repeat($pad_string, $right);
				break;
		}
	}else{
		return $input;
	}
}

function utf8_strlen($string = null) {
	// 将字符串分解为单元
	preg_match_all("/(<[^>]+>)|(.)/us", $string, $match);
	// 返回单元个数
	return count($match[0]);
}
function msubstr($str, $start=0, $length, $charset="utf-8", $suffix=true)
{
	/*if(function_exists("mb_substr")){
		if($suffix && utf8_strlen($str) > $length){
	return  utf8_strlen($str);
	//return mb_substr($str, $start, $length, $charset)."...";
	}else{
	return  utf8_strlen($str);
	//return mb_substr($str, $start, $length, $charset);
	}
	}elseif(function_exists('iconv_substr')) {
	if($suffix && utf8_strlen($str) > $length){
	return  utf8_strlen($str);
	//return iconv_substr($str,$start,$length,$charset)."...";
	}else{
	return  utf8_strlen($str);
	//return iconv_substr($str,$start,$length,$charset);
	}
	}
	$re['utf-8']   = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
	$re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
	$re['gbk']    = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
	$re['big5']   = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
	preg_match_all($re[$charset], $str, $match);
	$slice = join("",array_slice($match[0], $start, $length));
	if($suffix && utf8_strlen($str) > $length){
	return $slice."...";
	}else{
	return $slice;
	}*/
	preg_match_all("/(<[^>]+>)|(.)/us", $str, $match);
	if(count($match[0]) > $length){
		return join("",array_slice($match[0], $start, $length))."...";
	} else {
		return join("",$match[0]);
	}
}

function relative_to_absolute($content,$feed_url){

	preg_match('/(http|https|ftp):\/\//', $feed_url,$protocol);
	$server_url = preg_replace("/(http|https|ftp|news):\/\//", "", $feed_url);
	$server_url = preg_replace("/\/.*/", "", $server_url);

	if($server_url == ''){
		return $content;
	}

	if(isset($protocol[0])){
		$new_content = preg_replace('/href="\//', 'href="'.$protocol[0].$server_url.'/', $content);
		$new_content = preg_replace('/src="\//', 'src="'.$protocol[0].$server_url.'/', $new_content);
	}else{
		$new_content = $content;
	}
	return $new_content;

}

function generate_password( $length = 6 ) {
	// 密码字符集，可任意添加你需要的字符
	$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
// 	$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_ []{}<>~`+=,.;:/?|';
	$password = '';
	for ( $i = 0; $i < $length; $i++ )
	{
		// 这里提供两种字符获取方式
		// 第一种是使用 substr 截取$chars中的任意一位字符；
		// 第二种是取字符数组 $chars 的任意元素
		// $password .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
		$password .= $chars[ mt_rand(0, strlen($chars) - 1) ];
	}
	return $password;
}

/**
 * @param lat 纬度 lon 经度 raidus 单位米
 * return minLat,minLng,maxLat,maxLng
 */



/**
 *
 * @param  $lat 纬度
 * @param  $lng 经度
 * @param  $raidus 单位米
 * return minLat,minLng,maxLat,maxLng  stdClass
 */
function getAround($lat,$lng,$raidus){
	$PI = 3.14159265;
	$latitude = $lat;
	$longitude = $lng;
	$degree = (24901*1609)/360.0;
	$raidusMile = $raidus;
	$dpmLat = 1/$degree;
	$radiusLat = $dpmLat * $raidusMile;

	$minLat = $latitude - $radiusLat;
	$maxLat = $latitude + $radiusLat;

	$mpdLng = $degree * cos($latitude *($PI / 180));
	$dpmLng = 1/$mpdLng;
	$radiusLng = $dpmLng * $raidusMile;

	$minLng = $longitude - $radiusLng;
	$maxLng = $longitude + $radiusLng;

	$around = new stdClass();
	$around->minLat = $minLat;
	$around->maxLat = $maxLat;
	$around->minLng = $minLng;
	$around->maxLng = $maxLng;

	return $around;
}

/**
 * 根据两点经纬度 计算距离
 */
function getDistance($lat1,$lng1,$lat2,$lng2){
	$PI = 3.14159265;
	$r = 6378137;//地球平均半径(米)
// 	$lat1 = ($lat1 * pi())/180;
	$lat1 = ($lat1 * $PI)/180;//纬度转为角度
	$lng1 = ($lng1 * $PI)/180;//经度转为角度

	$lat2 = ($lat2 * $PI)/180;
	$lng2 = ($lng2 * $PI)/180;


	$calcLongitude = $lng2 - $lng1;
	$calcLatitude = $lat2 - $lat1;

	$stepOne = pow(sin($calcLatitude/2),2) +cos($lat1)*cos($lat2)*pow(sin($calcLongitude /2), 2);
	$stepTwo = 2 * asin(min(1,sqrt($stepOne)));

	$dis = $r * $stepTwo;
	return round($dis);

}

function getFakeOpenId() {
	$ip = get_client_ip();
	$fakeStr = $_SERVER['HTTP_USER_AGENT'] . $ip;
	$fakeStr = md5($fakeStr);
	$fakeOpenId = fake_prefix . $fakeStr;
	return $fakeOpenId;
}

function isMicroMessengerUserAgent() {
	$user_agent = $_SERVER['HTTP_USER_AGENT'];
	if (strpos($user_agent, 'MicroMessenger') === false) {
		return false;
	} else {
		return true;
	}
}
function isNativeApp() {
	$user_agent = $_SERVER['HTTP_USER_AGENT'];
	if (strpos($user_agent, 'nativeApp') === false) {
		return false;
	} else {
		return true;
	}
}


function isMicroMessengerVersionHigher5() {
	$user_agent = $_SERVER['HTTP_USER_AGENT'];
	$tmp = explode("micromessenger/",strtolower($user_agent));
	$bb = substr($tmp[1], 0 , 1);
	$check= ($bb>=5) ? true: false;
	return $check;
}


/**
 * *********************************************************************************************
 *                      下面是php版本>=5.4之后提供的功能(咱们版本是5.4.27, 所以得自己封装)
 * *********************************************************************************************
 */

/**
 * Provides functionality for array_column() to projects using PHP earlier than
 * version 5.5.
 * @copyright (c) 2015 WinterSilence (http://github.com/WinterSilence)
 * @license MIT
 */
if (!function_exists('array_column')) {
	/**
	 * Returns an array of values representing a single column from the input
	 * array.
	 * @param array $array A multi-dimensional array from which to pull a
	 *     column of values.
	 * @param mixed $columnKey The column of values to return. This value may
	 *     be the integer key of the column you wish to retrieve, or it may be
	 *     the string key name for an associative array. It may also be NULL to
	 *     return complete arrays (useful together with index_key to reindex
	 *     the array).
	 * @param mixed $indexKey The column to use as the index/keys for the
	 *     returned array. This value may be the integer key of the column, or
	 *     it may be the string key name.
	 * @return array
	 */
	function array_column(array $array, $columnKey, $indexKey = null)
	{
		$result = array();
		foreach ($array as $subArray) {
			if (!is_array($subArray)) {
				continue;
			} elseif (is_null($indexKey) && array_key_exists($columnKey, $subArray)) {
				$result[] = $subArray[$columnKey];
			} elseif (array_key_exists($indexKey, $subArray)) {
				if (is_null($columnKey)) {
					$result[$subArray[$indexKey]] = $subArray;
				} elseif (array_key_exists($columnKey, $subArray)) {
					$result[$subArray[$indexKey]] = $subArray[$columnKey];
				}
			}
		}
		return $result;
	}
}

/**
 * Generates cryptographically secure pseudo-random integers
 * @link http://php.net/manual/en/function.random-int.php
 * @param int $min The lowest value to be returned, which must be PHP_INT_MIN or higher.
 * @param int $max The highest value to be returned, which must be less than or equal to PHP_INT_MAX.
 * @return int Returns a cryptographically secure random integer in the range min to max, inclusive.
 * @since 7.0
 */
if (!function_exists('random_int')) {
	function random_int($min, $max) {
		if (!function_exists('mcrypt_create_iv')) {
			trigger_error(
				'mcrypt must be loaded for random_int to work',
				E_USER_WARNING
			);
			return null;
		}

		if (!is_int($min) || !is_int($max)) {
			trigger_error('$min and $max must be integer values', E_USER_NOTICE);
			$min = (int)$min;
			$max = (int)$max;
		}

		if ($min > $max) {
			trigger_error('$max can\'t be lesser than $min', E_USER_WARNING);
			return null;
		}

		$range = $counter = $max - $min;
		$bits = 1;

		while ($counter >>= 1) {
			++$bits;
		}

		$bytes = (int)max(ceil($bits/8), 1);
		$bitmask = pow(2, $bits) - 1;

		if ($bitmask >= PHP_INT_MAX) {
			$bitmask = PHP_INT_MAX;
		}

		do {
			$result = hexdec(
					bin2hex(
						mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM)
					)
				) & $bitmask;
		} while ($result > $range);

		return $result + $min;
	}
}

/**
 * *********************************************************************************************
 *                                   根据需要自己封装的函数
 * *********************************************************************************************
 */

if (!function_exists('array_sort')) {
	/**
	 * 二维数组排序
	 * 没有深层封装, 只封二维一个columnKey排序
	 *
	 * @param array  $array                     要排序的二维数组
	 * @param        $columnKey                 排序的依据字段
	 * @param string $sort_type asc | desc      排序方式
	 *
	 * @return array|bool                       如果不是数组返回false, 否则返回排序后的数组
	 */
	function array_sort(array $array, $columnKey, $sort_type = 'asc')
	{
		// 判断是不是数组
		if (!is_array($array))
			return false;

		// 拿出排序字段
		$array_row = array_column($array, $columnKey);

		// 排序
		$sort = ($sort_type == 'asc') ? SORT_ASC : SORT_DESC;
		array_multisort($array_row, $sort, $array);

		// 返回
		return $array;
	}
}
if (!function_exists('wxErrCode')) {
	/**
	 * 错误妈识别
	 *
	 * @param code
	 *
	 * @return string                       返回相应的错误信息
	 */
	function wxErrCode($code)
	{
		switch ($code) {
			case 40001: return '获取access_token时AppSecret错误，或者access_token无效';
			case 40002: return '不合法的凭证类型';
			case 40003: return '不合法的OpenID';
			case 40004: return '不合法的媒体文件类型';
			case 40005: return '不合法的文件类型';
			case 40006: return '不合法的文件大小';
			case 40007: return '不合法的媒体文件id';
			case 40008: return '不合法的消息类型';
			case 40009: return '不合法的图片文件大小';
			case 40010: return '不合法的语音文件大小';
			case 40011: return '不合法的视频文件大小';
			case 40012: return '不合法的缩略图文件大小';
			case 40013: return '不合法的APPID';
			case 40014: return '不合法的access_token';
			case 40015: return '不合法的菜单类型';
			case 40016: return '不合法的按钮个数';
			case 40017: return '不合法的按钮个数';
			case 40018: return '不合法的按钮名字长度';
			case 40019: return '不合法的按钮KEY长度';
			case 40020: return '不合法的按钮URL长度';
			case 40021: return '不合法的菜单版本号';
			case 40022: return '不合法的子菜单级数';
			case 40023: return '不合法的子菜单按钮个数';
			case 40024: return '不合法的子菜单按钮类型';
			case 40025: return '不合法的子菜单按钮名字长度';
			case 40026: return '不合法的子菜单按钮KEY长度';
			case 40027: return '不合法的子菜单按钮URL长度';
			case 40028: return '不合法的自定义菜单使用用户';
			case 40029: return '不合法的oauth_code';
			case 40030: return '不合法的refresh_token';
			case 40031: return '不合法的openid列表';
			case 40032: return '不合法的openid列表长度';
			case 40033: return '不合法的请求字符，不能包含\uxxxx格式的字符';
			case 40035: return '不合法的参数';
			case 40038: return '不合法的请求格式';
			case 40039: return '不合法的URL长度';
			case 40050: return '不合法的分组id';
			case 40051: return '分组名字不合法';
			case 41001: return '缺少access_token参数';
			case 41002: return '缺少appid参数';
			case 41003: return '缺少refresh_token参数';
			case 41004: return '缺少secret参数';
			case 41005: return '缺少多媒体文件数据';
			case 41006: return '缺少media_id参数';
			case 40130: return 'OpenId不少于两个';
			case 41007: return '缺少子菜单数据';
			case 41008: return '缺少oauth code';
			case 41009: return '缺少openid';
			case 42001: return 'access_token超时';
			case 42002: return 'refresh_token超时';
			case 42003: return 'oauth_code超时';
			case 43001: return '需要GET请求';
			case 43002: return '需要POST请求';
			case 43003: return '需要HTTPS请求';
			case 43004: return '消息接收者目前未关注公众号';
			case 43005: return '需要好友关系';
			case 44001: return '多媒体文件为空';
			case 44002: return 'POST的数据包为空';
			case 44003: return '图文消息内容为空';
			case 44004: return '文本消息内容为空';
			case 45001: return '多媒体文件大小超过限制';
			case 45002: return '消息内容超过限制';
			case 45003: return '标题字段超过限制';
			case 45004: return '描述字段超过限制';
			case 45005: return '链接字段超过限制';
			case 45006: return '图片链接字段超过限制';
			case 45007: return '语音播放时间超过限制';
			case 45008: return '图文消息超过限制';
			case 45009: return '接口调用超过限制';
			case 45010: return '创建菜单个数超过限制';
			case 45015: return '回复时间超出48小时';
			case 45016: return '系统分组，不允许修改';
			case 45017: return '分组名字过长';
			case 45018: return '分组数量超过上限';
			case 45028: return '群发次数上限';
			case 46001: return '不存在媒体数据';
			case 46002: return '不存在的菜单版本';
			case 46003: return '不存在的菜单数据';
			case 46004: return '不存在的用户';
			case 47001: return '解析JSON/XML内容错误';
			case 48001: return 'api功能未授权';
			case 50001: return '用户未授权该api';
			case 88000: return '没有留言权限';
		}
		return '';
	}
}

if (!function_exists('html2pdf')) {
	/**
	名称      html转换为pdf图片
	功能      将html页面转换为pdf图片(部分css样式无法识别)
	参数数量  2个
	1.必须    html代码 可以用file_get_contenth获取
	2.必须    生成pdf存放位置路径
	3.非必须  pdf宽
	4.非必须  pdf高
	返回值    图片名称
	实例      code($html,'img/1.pdf');
	 * */
	function html2pdf($html, $PATH, $w=414 ,$h=736){
		Vendor('MPDF60.mpdf');
		//设置中文字体(很重要 它会影响到第二步中 图片生成)
		$mpdf=new mPDF('utf-8');

		$mpdf->autoScriptToLang = true;
		$mpdf->autoLangToFont = true;
//设置pdf的尺寸
		$mpdf->WriteHTML('<pagebreak sheet-size="'.$w.'mm '.$h.'mm" />');


//设置pdf显示方式
		$mpdf->SetDisplayMode('fullpage');

//删除pdf第一页(由于设置pdf尺寸导致多出了一页)
		$mpdf->DeletePages(1,1);

		$mpdf->WriteHTML($html);

		$pdf_name = md5(time()).'.pdf';

		$mpdf->Output($PATH.$pdf_name);

		return $pdf_name;

	}
}
if (!function_exists('pdf2png')) {
	/**
	 * PDF2PNG
	 * @param $pdf  待处理的PDF文件
	 * @param $path 待保存的图片路径
	 * @param $page 待导出的页面 -1为全部 0为第一页 1为第二页
	 * @return      保存好的图片路径和文件名
	 */
	function pdf2png($pdf,$path,$page=-1)
	{
		if(!extension_loaded('imagick'))
		{
			return false;
		}
		if(!file_exists($pdf))
		{
			return false;
		}
		$im = new Imagick();
		$im->setResolution(96,96);
		$im->setCompressionQuality(500);
		if($page==-1)
			$im->readImage($pdf);
		else
			$im->readImage($pdf."[".$page."]");
		foreach ($im as $Key => $Var)
		{
			$Var->setImageFormat('jpg');
			$filename = $path."/". md5($Key.time()).'.jpg';
			if($Var->writeImage($filename) == true)
			{
				$Return[] = $filename;
			}
		}
		return $Return;
	}
}

if (!function_exists('imageExplode')) {
	/**
	名称      图片分割
	功能      一图分割成多图
	参数数量  2个
	$filename  必须    图片
	$p         非必须  分割的个数（默认为5）
	 * */
	function imageExplode($filename, $p=5){
		$imgPathArr='';
		// Get new sizes
		list($width, $height) = getimagesize($filename);
		$newwidth = $width;
		$newheight = floor($height / $p);
		$last = $height % $p;
		// Load
		$source = imagecreatefromjpeg($filename);
		for( $i=0 ; $i< $p; $i++ ){
			$_p = $newheight*$i;
			if( ( $i + 1 ) == $p )
				$newheight += $last;
			$thumb = ImageCreateTrueColor($newwidth, $newheight);
			imagecopyresized( $thumb, $source, 0, 0, 0, $_p, $newwidth,  $height, $width, $height);
			imagejpeg( $thumb ,ABSPATH. "Uploads/pdfs/iE_{$i}.jpg" ,100);
			$imgPathArr.=','.ABSPATH."Uploads/pdfs/iE_{$i}.jpg";
		}
		$imgPathArr=substr("$imgPathArr",1);
		return $imgPathArr;
	}
}
if (!function_exists('imageAddWatemark')) {
	/**
	 * 名称    图片添加水印
	 * 功能：  可以把图片添加图片水印和文字水印
	 * 参数：  6个
	 *$groundImage 图片地址（暂只支持GIF,JPG,PNG格式）
	 *$waterPos    水印位置，有10种状态，（0为随机位置,1为顶端居左，2为顶端居中，3为顶端居右,4为中部居左，5为中部居中，6为中部居右,7为底端居左，8为底端居中，9为底端居右）；
	 *$waterImage  图片水印，即作为水印的图片，暂只支持GIF,JPG,PNG格式 (如果文字水印传空)；
	 *$waterText   文字水印，即把文字作为为水印，支持ASCII码，不支持中文 (如果图片水印传空)；
	 *$textFont    文字大小，值为1、2、3、4或5，默认为5；  (如果图片水印传空）
	 *$textColor   文字颜色，值为十六进制颜色值，默认为#FF0000(红色)；(如果图片水印传空）
	 * 注意：Support GD 2.0，Support FreeType、GIF Read、GIF Create、JPG 、PNG
	 *$waterImage 和 $waterText 最好不要同时使用，选其中之一即可，优先使用 $waterImage。
	 *当$waterImage有效时，参数$waterString、$stringFont、$stringColor均不生效。
	 *加水印后的图片的文件名和 $groundImage 一样。
	 */
	function imageAddWatemark($groundImage,$waterPos=0,$waterImage="",$waterText="",$textFont=5,$textColor="#FF0000"){
		$isWaterImage = FALSE;
		$formatMsg = "暂不支持该文件格式，请用图片处理软件将图片转换为GIF、JPG、PNG格式。";
		//读取水印文件
		if(!empty($waterImage) && file_exists($waterImage))
		{
			$isWaterImage = TRUE;
			$water_info = getimagesize($waterImage);
			$water_w = $water_info[0];//取得水印图片的宽
			$water_h = $water_info[1];//取得水印图片的高
			switch($water_info[2])//取得水印图片的格式
			{
				case 1:$water_im = imagecreatefromgif($waterImage);break;
				case 2:$water_im = imagecreatefromjpeg($waterImage);break;
				case 3:$water_im = imagecreatefrompng($waterImage);break;
				default:die($formatMsg);
			}
		}

		//读取背景图片
		if(!empty($groundImage) && file_exists($groundImage))
		{
			$ground_info = getimagesize($groundImage);
			$ground_w = $ground_info[0];//取得背景图片的宽
			$ground_h = $ground_info[1];//取得背景图片的高
			switch($ground_info[2])//取得背景图片的格式
			{
				case 1:$ground_im = imagecreatefromgif($groundImage);break;
				case 2:$ground_im = imagecreatefromjpeg($groundImage);break;
				case 3:$ground_im = imagecreatefrompng($groundImage);break;
				default:die($formatMsg);
			}
		}else{

			return false;
		}
		//水印位置
		if($isWaterImage)//图片水印
		{
			$w = $water_w;
			$h = $water_h;
			$label = "图片的";
		}else{//文字水印
			$temp = imagettfbbox(ceil($textFont*5),0,"./cour.ttf",$waterText);//取得使用 TrueType 字体的文本的范围
			$w = $temp[2] - $temp[6];
			$h = $temp[3] - $temp[7];
			unset($temp);
			$label = "文字区域";
		}
		if( ($ground_w<$w) || ($ground_h<$h) )
		{
			return false;
		}
		switch($waterPos)
		{
			case 0://随机
				$posX = rand(0,($ground_w - $w));
				$posY = rand(0,($ground_h - $h));
				break;
			case 1://1为顶端居左
				$posX = 0;
				$posY = 0;
				break;
			case 2://2为顶端居中
				$posX = ($ground_w - $w) / 2;
				$posY = 0;
				break;
			case 3://3为顶端居右
				$posX = $ground_w - $w;
				$posY = 0;
				break;
			case 4://4为中部居左
				$posX = 0;
				$posY = ($ground_h - $h) / 2;
				break;
			case 5://5为中部居中
				$posX = ($ground_w - $w) / 2;
				$posY = ($ground_h - $h) / 2;
				break;
			case 6://6为中部居右
				$posX = $ground_w - $w;
				$posY = ($ground_h - $h) / 2;
				break;
			case 7://7为底端居左
				$posX = 0;
				$posY = $ground_h - $h;
				break;
			case 8://8为底端居中
				$posX = ($ground_w - $w) / 2;
				$posY = $ground_h - $h;
				break;
			case 9://9为底端居右
				$posX = $ground_w - $w - 10;   // -10 是距离右侧10px 可以自己调节
				$posY = $ground_h - $h - 10;   // -10 是距离底部10px 可以自己调节
				break;
			default://随机
				$posX = rand(0,($ground_w - $w));
				$posY = rand(0,($ground_h - $h));
				break;
		}
		//设定图像的混色模式
		imagealphablending($ground_im, true);
		if($isWaterImage)//图片水印
		{
			imagecopy($ground_im, $water_im, $posX, $posY, 0, 0, $water_w,$water_h);//拷贝水印到目标文件
		}else{//文字水印

			if( !empty($textColor) && (strlen($textColor)==7) )
			{
				$R = hexdec(substr($textColor,1,2));
				$G = hexdec(substr($textColor,3,2));
				$B = hexdec(substr($textColor,5));
			}
			else
			{
				return false;
			}
			imagestring ( $ground_im, $textFont, $posX, $posY, $waterText, imagecolorallocate($ground_im, $R, $G, $B));
		}

		//生成水印后的图片
		@unlink($groundImage);
		switch($ground_info[2])//取得背景图片的格式
		{
			case 1:imagegif($ground_im,$groundImage);break;
			case 2:imagejpeg($ground_im,$groundImage);break;
			case 3:imagepng($ground_im,$groundImage);break;
			default:die($errorMsg);
		}

		//释放内存
		if(isset($water_info)){
			unset($water_info);
		}
		if(isset($water_im)) {
			imagedestroy($water_im);
		}
		unset($ground_info);
		imagedestroy($ground_im);
		return $groundImage;

	}
}


if (!function_exists('diffBetweenTwoDays')) {
	/**
	 * 求两个日期之间相差的天数
	 * (针对1970年1月1日之后，求之前可以采用泰勒公式)
	 * @param string $day1	2017-10-09 12:00:00
	 * @param string $day2	2017-10-08 00:10:00
	 * @return number		本例中返回: 1
	 */
	function diffBetweenTwoDays ($day1, $day2)
	{
		$day1 = substr($day1, 0, 10);
		$day2 = substr($day2, 0, 10);
		$second1 = strtotime($day1);
		$second2 = strtotime($day2);

		if ($second1 < $second2) {
			$tmp = $second2;
			$second2 = $second1;
			$second1 = $tmp;
		}
		return ($second1 - $second2) / 86400;
	}
}



/**
 * 创建对应的文件夹
 * @param $save_dir /文件夹名称
 * @throws Exception
 */
function createDir($save_dir)
{
	//$save_dir = APP_PATH.'../updateDoc/datas';
	if (trim($save_dir) == '') {
		//保存的文件夹
		$save_dir = './';
	}
	if (0 !== strrpos($save_dir, '/')) {
		$save_dir .= '/';
	}
	//创建保存目录
	if (!file_exists($save_dir) && !mkdir($save_dir, 0777, true)) {
		//创建文件夹失败
		throw new Exception('创建文件夹失败');
	}
}
?>
